/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Describe：字节流协议，所有的数据存放在byte[]中，客户端和服务端按照约定的数据类型和顺序解析各个参数。
* 支持int,float,string,byte[]这几种类型数据
 * 规定前两个参数必须是字符串，第一个表示客户端请求的类型，第二个表示请求的协议名称
 * 请求类型或协议名称由协议的长度和内容两部分组成，长度是int类型，占用4个字节
* CreateTime：2020-08-15 18:03:31
* Version：1.0
* Modify Recorder：
*************************************************/
using System;
using System.Linq;
using System.Text;

namespace TinyToolKit.Network
{
    public class ProtocolBytes : ProtocolBase 
    {
        private byte[] bytes;

        /// <summary>
        /// 解码
        /// </summary>
        public override ProtocolBase Decode(byte[] readBuff)
        {
            bytes = readBuff;
            return this;
        }

        /// <summary>
        /// 编码
        /// </summary>
        public override byte[] Encode()
        {
            return bytes;
        }

        public override RequestType GetRequest()
        {
            string request = GetString(0);
            if (request == "") return RequestType.None;
            return (RequestType)Enum.Parse(typeof(RequestType), request);
        }

        public override string GetName()
        {
            int start = 0;
            GetString(start,ref start);
            string name = GetString(start,ref start);
            return name;
        }

        //添加字符串，包含字符串大小的字节还有字符串本身的字节
        public void AddString(string str)
        {
            byte[] strBytes = Encoding.UTF8.GetBytes(str);
            byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);

            if (bytes == null)
                bytes = lenBytes.Concat(strBytes).ToArray();
            else
                bytes = bytes.Concat(lenBytes).Concat(strBytes).ToArray();
        }

        public string GetString(int start,ref int end)
        {
            if (bytes == null) return "";
            if (bytes.Length < start + sizeof(Int32)) return "";
            int len = BitConverter.ToInt32(bytes, start);
            if (bytes.Length < start + sizeof(Int32) + len) return "";
            string str = Encoding.UTF8.GetString(bytes, start + sizeof(Int32), len);
            end = start + sizeof(Int32) + len;
            return str;
        }

        public string GetString(int start)
        {
            int end = 0;
            return GetString(start, ref end);
        }

        //添加整数，占用四个字节
        public void AddInt(int num)
        {
            byte[] numBytes = BitConverter.GetBytes(num);
            if (bytes == null)
                bytes = numBytes;
            else
                bytes = bytes.Concat(numBytes).ToArray();
        }

        public int GetInt(int start, ref int end)
        {
            if (bytes == null) return 0;
            if (bytes.Length < start + sizeof(Int32)) return 0;
            end = start + sizeof(Int32);
            return BitConverter.ToInt32(bytes, start);
        }

        public int GetInt(int start)
        {
            int end = 0;
            return GetInt(start, ref end);
        }

        //获取浮点值类型，占8个字节
        public void AddFloat(float num)
        {
            byte[] numBytes = BitConverter.GetBytes(num);
            if (bytes == null)
                bytes = numBytes;
            else
                bytes = bytes.Concat(numBytes).ToArray();
        }

        public float GetFloat(int start, ref int end)
        {
            if (bytes == null) return 0;
            if (bytes.Length < start + sizeof(float)) return 0;
            end = start + sizeof(float);
            return BitConverter.ToSingle(bytes, start);
        }

        public float GetFloat(int start)
        {
            int end = 0;
            return GetFloat(start, ref end);
        }

        //添加字节数组，包含数组大小的字节还有数组本身的字节
        public void AddBytes(byte[] data) 
        {
            byte[] lenBytes = BitConverter.GetBytes(data.Length);

            if (bytes == null)
                bytes = lenBytes.Concat(data).ToArray();
            else
                bytes = bytes.Concat(lenBytes).Concat(data).ToArray();
        }

        public byte[] GetBytes(int start, ref int end)
        {
            if (bytes == null) return null;
            if (bytes.Length < start + sizeof(Int32)) return null;
            int len = BitConverter.ToInt32(bytes, start);
            if (bytes.Length < start + sizeof(Int32) + len) return null;
            byte[] tempData = new byte[len];
            Array.Copy(bytes, start, tempData, 0, len);
            end = start + sizeof(Int32) + len;
            return tempData;
        }
    }
}

